﻿using Ardalis.GuardClauses;
using DDD.Core.DependencyInjection;
using DDD.Core.Vaildate;
using DDD.Domain.Abstract.Entities;
using DDD.Domain.Abstract.Entities.IAbiltly;
using DDD.Domain.Abstract.GuidGenerator;
using DDD.Domain.DomainEvents.UserDomainEvents;
using DDD.Domain.Enums;
using DDD.Domain.ValueObjects;

namespace DDD.Domain.Entities
{
    public sealed class User : Entity<Guid>, ICreateTime
    {
        public User() { }

        public User(string userName, string phone, string email, string password, SexEnum sex, Address address)
        {
             SetId()
            .SetUserName(userName)
            .SetPhone(phone)
            .SetEmail(email)
            .SetPassword(password)
            .SetSex(sex)
            .SetAddress(address)
            .SetCreateTime();
        }

        public string UserName { get; private set; }

        public string Phone { get; private set; }

        public string Email { get; private set; }

        public string Password { get; private set; }

        public SexEnum Sex { get; private set; }

        public Address Address { get; private set; }

        public DateTime CreateTime { get; private set; }

        #region behaviours

        public User Create(string userName, string phone, string email, string password, SexEnum sex, Address address)
        {
            var user = new User(userName, phone, email, password, sex, address);
            user.AddDomainEvent(new CreateUserDomainEvent()
            {
                User = user
            });

            return user;
        }

        #endregion


        #region set property

        public User SetUserName(string userName) 
        {
            this.UserName = Guard.Against.ValueIsNotNullOrEmpty(userName); 
            return this;
        }

        public User SetPhone(string phone) 
        {
            this.Phone = Guard.Against.PhoneFormatIsRight(phone);
            return this;
        }

        public User SetEmail(string email)
        {
            this.Email = Guard.Against.EmailFormatIsRight(email);
            return this;
        }

        public User SetPassword(string password)
        {
            this.Password= Guard.Against.ValueIsNotNullOrEmpty(password);
            return this;
        }

        public User SetSex(SexEnum sex)
        {
            this.Sex = sex;
            return this;
        }

        public User SetAddress(Address address)
        {
            this.Address = address;
            return this;
        }

        private User SetId()
        {
            this.Id = IOC.KeyResolve<IGuidGenerator>(nameof(SequentialAtEndGuidGenerator)).Create();
            return this;
        }

        private User SetCreateTime()
        {
            this.CreateTime=DateTime.Now;
            return this;
        }

        #endregion
    }
}
